package gld.algo.tlc;

import gld.infra.Drivelane;
import gld.infra.InfraException;
import gld.infra.Infrastructure;
import gld.infra.Node;
import gld.infra.Roaduser;
import gld.infra.Sign;
import gld.xml.XMLCannotSaveException;
import gld.xml.XMLElement;

import java.awt.Point;
import java.util.LinkedList;
import java.util.ListIterator;

public class BroadwayCoFields extends TLController {
	protected int PHASE_MIN = 10;
	protected float GAMMA = 0.05f;
	
	public final static String shortXMLName="Co_Fields";
	
	public BroadwayCoFields(Infrastructure infra) 
	{	
		super(infra);
		super.setKeepSwitchControl(true);
	}
	
	public void setInfrastructure(Infrastructure i) 
	{	super.setInfrastructure(i);
	}
	
	public void setPhaseMin(int pm) {
		PHASE_MIN = pm;
		System.out.println("#######  sotl-platoon phase_min set to "+pm);
	}
	public int getPhaseMin() {
		return PHASE_MIN;
	}
	/** 
	 * if trafficlight was switched green at last cycle 
	 * 	- sets kappa of tld to 0
	 * 	- resets minimal phase to PHASE_MIN
	 * */
	public void updateTLDs() {
		
		//System.out.println("#################################################");	
		for (int i = 0; i < tld.length; i++) { // for all nodes
			boolean switched = false;
			
			for (int j = 0; j < tld[i].length; j++)
				if (tld[i][j].getTL().getCycleSwitched()==getCurCycle()-1)
					switched = true;
			
			if(switched) {
				if(!tld[i][0].getTL().getNode().getKeepTLDFlag()) {
					tld[i][0].getTL().getNode().setKeepTLDFlag(true);
					tld[i][0].getTL().getNode().setPhaseMinimal(PHASE_MIN);
					for (int j = 0; j < tld[i].length; j++) 
						if (tld[i][j].getTL().getState())
							tld[i][j].setQValue(0);
				}
			}
		}	
	}

	public float countGreenField(Drivelane lane){
	float GF = (((float)lane.getNumRoadusersWaiting())/((float)lane.getLength()));
	try {
		Drivelane[] inboundLane = lane.getNodeComesFrom().getInboundLanes();
		for(int i=0; i<inboundLane.length; i++){
			GF = GF + GAMMA * (float)inboundLane[i].getNumRoadusersWaiting()/(float)inboundLane[i].getLength();
			//System.out.println("Computing GF = " + GF);
		}
	} catch (InfraException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}

		return GF;
	}
	
	public TLDecision[][] decideTLs()
	{	// System.out.println("Current cycle = "+
		// (getInfrastructure().getCurCycle()));
		TLDecision currentDec;
		Drivelane curLane;
		
		//System.out.println("#### TLDATA-"+this.getCurCycle()+" ####");
		
		//adjust data after last cycle
		updateTLDs();
		//
		
		for (int i = 0; i < tld.length; i++) { // for all nodes
			Node currentNode = null;
			for (int j = 0; j < tld[i].length; j++)
				if (currentNode == null) currentNode= tld[i][j].getTL().getNode();
			
			if (currentNode != null && currentNode.getKeepTLDFlag()) {
				currentNode.decrPhaseMinimal();
				//System.out.println("Decr PHASEMIN for node "+ tld[i][0].getTL().getNode().getId());		
			}
			
			for (int j = 0; j < tld[i].length; j++) { // for all inbound lanes in node
				
				currentDec = tld[i][j];
				curLane = tld[i][j].getTL().getLane();
				float cntr = countGreenField(curLane);

				if (!tld[i][j].getTL().getState())
					currentDec.setQValue(cntr);

				if (currentNode.getPhaseMinimal() <= 0 ) {
					//System.out.println("REQUEST APPROVED FOR NODE "+ currentNode.getId());
					//currentDec.setQValue(currentDec.getKappa());
					currentDec.setQValue(cntr);
					currentNode.setKeepTLDFlag(false);
					//System.out.println("kappa is "+currentDec.getKappa());
					// curDec.setQValue(1);
					/*System.out.println("+ PROPOSITION <C-"+getCurCycle()+
							"> <Node: "+tld[i][j].getTL().getNode().getId()+
							"> <tl: "+currentDec.getTL().getId()+
							"> <kappa: "+currentDec.getKappa()+
							"> <Q = " + tld[i][j].getQValue() +
							"> <wait: "+currentDec.getPhaseMinimal()+">");*/
				}
				else 
				{
					currentDec.setQValue(0);
				/*	System.out.println("- REJECTED <C-"+getCurCycle()+
							"> <Node: "+tld[i][j].getTL().getNode().getId()+
							"> <tl: "+curDec.getTL().getId()+
							"> <kappa: "+curDec.getKappa()+
							"> <Q = " + tld[i][j].getQValue() +
							"> <wait: "+curDec.getPhaseMinimal()+">");*/
				}
			}
		}
		return tld;
	}

	public void updateRoaduserMove(Roaduser _ru, Drivelane _prevlane, Sign _prevsign, int _prevpos, Drivelane _dlanenow, Sign _signnow, int _posnow, Drivelane[] _possiblelanes, Point[] _ranges, Drivelane desired)
	{
	    // Not needed
	}
	
	// XMLSerializable implementation
	public XMLElement saveSelf () throws XMLCannotSaveException
	{	XMLElement result=super.saveSelf();
		result.setName(shortXMLName);
		return result;
	}
  
 	public String getXMLName ()
	{ 	return "model."+shortXMLName;
	}


}

